/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number}
 */
 var findTargetSumWays = function(nums, target) {
  // 背包问题 
  // dp[j]表示和为j的表达书的数目
  // dp[j]可以由dp[j-nums[i]]推到过来 当有1这个元素的时候 dp[j] = dp[j-1] 当这个元素有很多的时候就是一个累加的操作
  let sum = nums.reduce((sum,val)=>sum + val)
  if(Math.abs(target) > sum) return 0 // 如果这个目标绝对值大于sum 那么就直接返回0 没有办法让和是sum
  if((target + sum)%2){
      return 0 // 如果sum 和target的和是一个奇数的话 那么除以二就是小数 那么就不可能整数加载一起是个小数
  }
  let halfSum = Math.floor((target +sum) / 2) // 求得这个一半的值 这个就是目的就是求数组的的数字的和等于这个halfsum
  let dp = new Array(halfSum+1).fill(0) // 初始化dp数组 dp[j]表示 和为j的有多少种数组的选择方法 初始值是0 是为了以后更好的累加
  dp[0] = 1 // 和为0的数组有1中选择方法 就是什么都不选
  for(let i = 0;i < nums.length;i++){
      // 遍历数组
      for(let j = halfSum; j >= nums[i];j--){
          // 从后向前遍历 判断这个halfsumdp[j]等于前面的所有的和
          dp[j] += dp[j-nums[i]] // 这个的值就是存在nums[i]的话 就是dp[j-nums[i]]
      }
  }
  // 最后返回最后的值
  return dp[halfSum]
};